package ca.etsmtl.log120.tp3.rangs;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import ca.etsmtl.log120.tp3.cartes.Carte;
import ca.etsmtl.log120.tp3.cartes.CouleurCarte;
import ca.etsmtl.log120.tp3.cartes.Denomination;
import ca.etsmtl.log120.tp3.mains.Main;

/******************************************************
Cours : LOG120
Session : E2011
Groupe : 01
Projet : Laboratoire #3
Etudiants : Nicolas Blais Miko
 	 		Yohan Trepanier-Montpetit
Codes perm. : BLAN24079109
			  TREY16079108
Professeur : Chamseddine Talhi
Charge de labo : Eric Goulet
Nom du fichier : ListeAnalyseurs.java
Date cree : 2011-07-06
Date dern. modif. 2011-07-06
*************************************************** ****
Historique des modifications
*************************************************** ****

***************************************************/

public class UtilMain {
	
	public static final int NOMBRE_CARTES_DANS_MAIN = 5;

	/**
	 * Indique la denomination du nombre de cartes identiques 
	 * recherchees, si present
	 * @param main la main a verifier
	 * @param nombre le nombre de repetitions a trouver
	 * @return la denomination si trouvee, null si rien n'est trouve
	 */
	public static Denomination isIdentique(Main main, int nombre){
		List<Carte> mainSorted = (Main)main.clone(); //Pour la main triee
		Collections.sort(mainSorted);  //Tri de la main
		//Tableau pour le nombre de cartes identiques
		int nombrePareil = 0; 

		//pour chaque carte de la main, on regarde si elle est identique a la suivante
		//(On commence par les cartes hautes)
		for(int i = mainSorted.size()-1; i >= 1; i--){
			
			Denomination precedent = mainSorted.get(i - 1).getDenomination();
			
			//si oui, on compte le nombre de cartes identiques
			if(mainSorted.get(i).getDenomination().equals(precedent))
				nombrePareil++;
			else
				nombrePareil = 0;
			
			//si on atteint le nombre desire, on retourne la denomination
			if(nombrePareil >= nombre-1)
				return mainSorted.get(i).getDenomination();
			
		}
		
		return null;
	}
	
	/**
	 * Cette methode statique recoit une main et va verifier si cette main est de rang Couleur
	 * Pour ce faire on parcours le tableau de toute les couleurs possibles
	 * Pour chaque couleur, on incremente une variable chaque fois qu'une carte est de cette couleur en parcourant le tableau des cartes
	 * @param main La main pour laquelle un cherche le rang Couleur
	 * @param nombreRecherche Le nombre de cartes de meme couleur recherche
	 * @return La couleur pour laquelle on a un rang Couleur ou null si la main n'a pas le nombre requis de cartes de meme couleur
	 */
	public static Denomination isCouleursPareilles(Main main, int nombreRecherche){
		
		int tmp = 0; //Variable temporaire
		
		//On parcours chaque couleur
		for(int i = 0; i < CouleurCarte.COULEURS.size(); i++){
				
			//On parcours toutes les cartes de la main
				for(Carte carte: main){
					
					//Si la carte que l'on regarde est de la meme couleur que celle que l'on recherche, 
					//on incremente une variable temporaire
					if(carte.getCouleur().equals(CouleurCarte.COULEURS.get(i)))
						tmp++;
				}
				
				//Si on a detecte au moins un nombre X de cartes de 
				//cette couleur, on retourne la couleur
				if(tmp >= nombreRecherche)
					return UtilMain.getHighestCard(main);
				else
					tmp = 0;
		}
		
		return null;
	}

	/**
	 * On prend chaque carte et on regarde si la suivante est la denomination d'apres
	 * @param main La main a analyser
	 * @param nombreRecherche Le nombre de cartes suivies recherchees
	 * @return Si la denomination de la premiere carte de la suite si le pattern a ete trouve, null sinon
	 */
	public static Denomination isSuite(Main main, int nombreRecherche){
		
		Main mainSorted = main.clone();
		
		//checkForAs(mainSorted);
		
		Collections.sort(mainSorted);
		
		int nombreDansSuite = 0; //Pour le nombre de carte suivies trouvees
		Denomination carteActuelle = mainSorted.get(0).getDenomination(); //Pour la carte courante
		
		//On passe toute la main.
		for(int i = 0; i <= mainSorted.size() - 1; i++){
			
			Denomination nextCard;
			
			try{
				//On met la carte suivante en memoire
				nextCard = mainSorted.get(i + 1).getDenomination();
			}catch(IndexOutOfBoundsException e){
				nextCard = null;
			}
		
			//Variable booleenne qui verifie si on est dans le cas ou l'as suit le roi
			boolean nextIsAsFin = Denomination.DENOMINATIONS.indexOf(carteActuelle) == 12 && Denomination.DENOMINATIONS.indexOf(nextCard) == 0;
			//Variable booleenne qui verifie si on est dans le cas d'une suite a la hauteur de 5
			boolean nextIsAs = Denomination.DENOMINATIONS.indexOf(carteActuelle) == 4 && Denomination.DENOMINATIONS.indexOf(nextCard) == 0 && nombreDansSuite == 3;
			//Si le chiffre de la carte courante + 1 donne le chiffre de la carte suivante,
			//on a une suite
			if(Denomination.DENOMINATIONS.indexOf(carteActuelle) + 1 == Denomination.DENOMINATIONS.indexOf(nextCard) || nextIsAsFin || nextIsAs){
				nombreDansSuite++;  //on se rappelle a combien de cartes on est rendu
				carteActuelle = mainSorted.get(i + 1).getDenomination();
				
				//si on atteint le nombre de cartes suivies voulues, 
				//on retourne la denomination de la derniere carte de la suite
				if(nombreDansSuite == nombreRecherche - 1)
					if(!nextIsAs)
						return carteActuelle;
					else
						return Denomination.CINQ;
				
				
			}else{ //si ca se suit pas, on n'a plus de nombre dans la suite
				nombreDansSuite = 0;
			}
		}
		
		//si on a pas atteint le nombre voulu, on retournu null
		return null;
	
	}


	/**
	 * Enleve les cartes possedant une certaine denomination
	 * @param main la main à traiter
	 * @param denom le denominateur de carte a enlever
	 * @return la main raccourcie
	 */
	public static Main removeDenom(Main main, Denomination denom){
	//	Enlever les cartes trouvees
		Main mainMod = main.clone();
		ArrayList<Carte> toRemove = new ArrayList<Carte>();
		for(Carte c: mainMod){
			if(c.getDenomination().equals(denom))
				toRemove.add(c);
		}
		
		mainMod.removeAll(toRemove);
		return mainMod;
	}
	
	/**
	 * Methode statique permettant de comparer le tableau resteMain de deux objets du meme rang
	 * @param rang1 Le rang avec lequel on compare
	 * @param rang2 Le rang pour lequel on fait la comparaison
	 * @param sizeTabKickers La taille du tableau resteMain (depend du rang qui appel)
	 * @return -1 si le premier rang est plus fort, 1 si c'est le deuxieme et 0 si ils sont egaux
	 */
	public static int compareKickers(AbstractRangAnalysable rang1, AbstractRangAnalysable rang2, int sizeTabKickers){
		
		//On utilise deux tableau temporaires
		Denomination[] rang1Tab = rang1.getResteMain();
		Denomination[] rang2Tab = rang2.getResteMain();
		
		//On parcours ces tableaux et on compare a chaque indice les deux denomination, s'il y a un gagnant, on retourne le resultat,
		// sinon on continue
		for(int i = 0; i < sizeTabKickers; i++){
			
			if(rang1Tab[i].compareTo(rang2Tab[i]) > 0)
				return -1;
			else if(rang1Tab[i].compareTo(rang2Tab[i]) < 0)
				return 1;
		}return 0; //Si aucun gagnant n'a ete trouve, on retourne 0
	}

	/**
	 * Methode statique qui retourne la plus haute denomination d'une main
	 * @param main La main pour laquelle on cherche la plus haute denomination
	 * @return La denomination la plus haute de la main
	 */
	public static Denomination getHighestCard(Main main) {
		
		//On utilise un objet temporaire etant la plus faible carte
		Denomination tmp = Denomination.DEUX;
		
		//Pour chaque carte dans la main, si la denomination de cette carte est plus forte que la denomination temporaire,
		//on remplace la denomination temporaire par la denomination de la carte
		for(Carte carte: main){
			
			if(carte.getDenomination().compareTo(tmp) > 0)
				tmp = carte.getDenomination();
		}
		
		//On retourne la denomination temporaire
		return tmp;
	}
	
}
